/* 
 * Shuriken is the legal property of its developers. Please refer to the
 * COPYRIGHT file distributed with this
 * source distribution.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections.Generic;
using System.Text;
using Shuriken.Base;
using Shuriken.Core; 
using Shuriken.Core.Store;
using Shuriken.Core.Utils;
using System.Reflection;
using System.IO; 

namespace Shuriken.Core
{
    public class RegistrationManager
    {
        private static RegistrationManager m_default;
        private List<QNModule> m_Modules; 

        /// <summary>
        /// Returns the default instance
        /// </summary>
        /// <returns>default instance</returns>
        public static RegistrationManager GetDefaultInstance()
        {
            if(m_default == null)
            {
                m_default = new RegistrationManager();
            }

            return m_default;
        }

        public RegistrationManager()
        {
            m_Modules = new List<QNModule>();
        }

        public void LoadModules()
        {
            ApplicationServiceHost.InitializeService(new ApplicationService());

            // Loading modules 
            List<Assembly> plugins = GetPluginAssemblies();
            Assembly internal_module = GetInternalModuleAssembly();
            plugins.Add(internal_module);
            
            // Loading internal module
            // LoadModulesFromAssembly(internal_modules);

            // Loading modules found plugins folder  
            foreach(Assembly plugin in plugins)
            {
                m_Modules.Add(new QNModule(plugin));
            }
            
            // Initializing Modules 
            foreach (QNModule mod in m_Modules)
            {
                try
                {
                    mod.Init();
                }
                catch (Exception excp)
                {
                    Tracer.WriteError("Failed to initialize " + mod.Name + " module. Reason: " + excp.ToString(), "Module");

#if DEBUG 
                    throw excp; 
#endif
                }
            }

        }

        private List<Assembly> GetPluginAssemblies()
        {
            List<Assembly> plugins = new List<Assembly>();
            string pluginPath = ApplicationEnvironment.ApplicationPluginDirectory;
            
            if(Directory.Exists(pluginPath))
            {
                string[] filesToTest = Directory.GetFiles(pluginPath, "*.dll");
                foreach (string file in filesToTest)
                {
                    try
                    {
                        Assembly a = Assembly.LoadFrom(file);
                        plugins.Add(a);
                    }
                    catch (Exception excp)
                    {
                        Tracer.WriteWarning("Failed to load plugin: " + file + ". Error: " + excp.Message);
                    }
                }
            }
            return plugins; 
        }

        /// <summary>
        /// Gets the assembly where internal modules are stored. 
        /// </summary>
        /// <returns>Internal modules assembly</returns>
        private Assembly GetInternalModuleAssembly()
        {
            Assembly module = null;
            
            string location = System.Reflection.Assembly.GetEntryAssembly().Location;
            string path = System.IO.Path.GetDirectoryName(location);
            string asm_path = System.IO.Path.Combine(path, "Shuriken.Modules.dll");

            try
            {
                module = Assembly.LoadFile(asm_path);
            }
            catch (Exception)
            {
                Tracer.WriteWarning("Could not load internal modules assembly!");
                module = null;
            }

            return module;
        }
    }
}
